﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace Galaxy_Wars
{
    class NetworkClient
    {
        private string ip;
        public TcpClient client;

        public NetworkClient(string ip) {
            this.ip = ip;
            connect();
        }

        public void connect()
        {
            Boolean done = false;
            try
            {
                client = new TcpClient("127.0.0.1", 2750);
                
            }

            catch (SocketException)
            {
                Debug.WriteLine("Connection to The Galaxy Wars Server Failed");
                done = true;
            }
        }

        public string ReadMessage()
        {
            byte[] buffer = new byte[512];
            int totalRead = 0;
            //read bytes until stream indicates there are no more
            do
            {
                try
                {
                    int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead);
                    totalRead += read;
                }
                catch (IOException) { Console.WriteLine("Connection err"); }
                //Console.WriteLine("ReadMessage: " + read);
            } while (client.GetStream().DataAvailable);

            return Encoding.Unicode.GetString(buffer, 0, totalRead);
        }

        public void SendMessage(string message)
        {
            try
            {
                byte[] bytes = Encoding.Unicode.GetBytes(message);
                client.GetStream().Write(bytes, 0, bytes.Length);
            }
            catch (IOException)
            {

            }
            catch (InvalidOperationException)
            {

            }
        }

        //Receive Objects from .....
        //Send Objects to clients
        public void sendObject(SendObj o)
        {
            IFormatter formatter = new BinaryFormatter();

            NetworkStream strm = client.GetStream();
            formatter.Serialize(strm, o);

            strm.Close();
        }

        //Receive Objects from .....
        public object receiveObject()
        {

            NetworkStream strm = client.GetStream();
            IFormatter formatter = new BinaryFormatter();

            Object o = (Object)formatter.Deserialize(strm);

            strm.Close();
            Debug.WriteLine(""+o);
            return o;
        }

        public void SendObjecttoByte(Object obj)
        {
            try
            {
                byte[] bytes = ObjectToByteArray(obj);
                Console.WriteLine("Object to byte array OK\r\nSize: " + bytes.Length);
                client.GetStream().Write(bytes, 0, bytes.Length);
                Console.WriteLine("Written the bytes");
            }
            catch (IOException)
            {

            }
            catch (InvalidOperationException)
            {

            }
        }

        public Object ReceiveObjectfromByte()
        {
            byte[] buffer = new byte[5242880]; //5 MeBiByte
            int totalRead = 0;
            //read bytes until stream indicates there are no more
            do
            {
                int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead);
                totalRead += read;
                //Console.WriteLine("ReadMessage: " + read);
            } while (client.GetStream().DataAvailable);

            return ByteArrayToObject(buffer);
        }

        // Convert an object to a byte array
        private byte[] ObjectToByteArray(Object obj)
        {
            if (obj == null)
                return null;
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }

        // Convert a byte array to an Object
        private Object ByteArrayToObject(byte[] arrBytes)
        {
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter binForm = new BinaryFormatter();
            memStream.Write(arrBytes, 0, arrBytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            SendObj obj = (SendObj)binForm.Deserialize(memStream);
            return obj;
        }
    }
}
